import key from 'keymaster'

import { asyncTopicConstants } from '../constants/asyncTopicConstants'
import { syncTopicConstants } from '../constants/syncTopicConstants'

import * as service from '../utils/request'


const GlobalModel = {
    namespace: 'listModel',
    state: {
        searchResult: [],                     // 当前搜索结果
        cursor: 0,                            // searchResult的游标
        relativeCursor: 1,
        searchDataSource: "pluginDefine",     // configDefine:搜索结果来自配置定义或动态生成，动态生成通常是list模式下的搜索结果
        listPluginInfo: null,                 // 当前listPlugin详细信息
        searchActionInfo: null                // 当前用户搜索的相关信息
    },
    effects: {

        *doKeyUpOrDown({ payload, callback }, { call, put, select }) {

            const { cursor, searchResult } = yield select(state => state.listModel)
            if (searchResult.length == 0) {
                return
            }
            if (payload.keyCode == "ArrowDown") {
                yield put({ type: "save", payload: { cursor: cursor + 1 <= searchResult.length ? cursor + 1 : searchResult.length } })
            } else if (payload.keyCode == "ArrowUp") {
                yield put({ type: "save", payload: { cursor: cursor - 1 >= 0 ? cursor - 1 : 0 } })
            }
        },


        *doKeyDown({ payload, callback }, { call, put, select }) {
            let cnt = yield select(state => state.listModel.searchResult.length)
            if (cnt > 10) {
                cnt = 10
            }
            const height = (cnt + 1) * 60
            service.onEmit(asyncTopicConstants.setHeight, height)
        },


        *doKeyEnter({ payload, callback }, { call, put, select }) {
            const { cursor, searchResult } = yield select(state => state.listModel)
            const thePlugin = searchResult[cursor]
            yield put({ type: "doRunPluginByBackend", payload: { plugin: thePlugin } })

        },



        *doRunPluginByBackend({ payload, callback }, { call, put, select }) {
            const { searchDataSource, searchActionInfo } = yield select(state => state.listModel)
            const plugin = payload.plugin
            if (searchDataSource == "pluginDefine") {
                // 执行doRunPluginByPluginDefine
                const pluginInfo = plugin.extInfo.cmdDetailInfo
                const thePayload = {
                    plugin: pluginInfo,
                    input: searchActionInfo.input,
                    subInput: searchActionInfo.subInput,
                    extInfo: searchActionInfo.extInfo,
                    type: searchActionInfo.iconType,
                    source: "search"
                }
                service.onEmit(asyncTopicConstants.doRunPlugin, thePayload)

            } else if (searchDataSource == "codeDefine") {
                // 执行doRunPluginByCodeDefine
                const listPluginInfo = yield select(state => state.listModel.listPluginInfo)
                const code = listPluginInfo.plugin.cmdInfo.featureInfo.code
                const itemData = plugin
                const action = {
                    extInfo: listPluginInfo.extInfo,
                    input: listPluginInfo.input,
                    subInput: listPluginInfo.subInput,
                    type: listPluginInfo.type,
                    source: "search"
                }
                // 列表插件只运行下钻一层，通过获取到的action及用户的选项进行决策
                try {
                    window.exports[code].select(action, itemData)
                }
                catch (e) {
                    // todo 执行异常，发送系统消息
                }
            }
        },

        /*
        * desc: 执行list模式插件的自定义搜索命令
        */
        *doSearchForListPlugin({ payload, callback }, { call, put, select }) {

            const listPluginInfo = yield select(state => state.listModel.listPluginInfo)
            console.info("listPluginInfo", listPluginInfo)
            const code = listPluginInfo.plugin.cmdInfo.featureInfo.code
            const action = {
                extInfo: listPluginInfo.extInfo,
                input: payload.input,
                subInput: listPluginInfo.subInput,
                type: listPluginInfo.type,
                source: "search"
            }
            const keyword = payload.input
            let theData = []
            // 搜索显示的回调函数
            const callbackSetList = (data) => {
                theData = data
            }

            if (window.exports[code]) {
                try {
                    window.exports[code].search(action, keyword, callbackSetList)
                } catch (e) {
                    // todo 执行异常，发送系统消息
                    console.info("e", e)
                }
            }

            yield put({
                type: "save", payload: {
                    searchResult: theData,
                    cursor: 0,
                    relativeCursor: 1,
                    searchDataSource: "codeDefine",
                }
            })
        },

        *updateMainWinHeight({ payload, callback }, { call, put, select }) {
            let cnt = yield select(state => state.listModel.searchResult.length)
            if (cnt > 10) {
                cnt = 10
            }
            const height = (cnt + 1) * 60
            service.onEmit(asyncTopicConstants.setHeight, height)
        },

        *doEmptySearchResult({ payload, callback }, { call, put, select }) {
            yield put({ type: 'save', payload: { searchResult: [], searchDataSource: "pluginDefine" } })
        },


    },
    reducers: {
        save(state, { payload }) {
            return { ...state, ...payload };
        },

        // compose搜索结果，转换为列表
        doMergeSeachResult(state, { payload }) {
            const resultData = []
            for (let item of payload.searchResult) {
                resultData.push(
                    {
                        key: item.cmdId,
                        featureIcon: item.cmdInfo?.featureInfo.icon,
                        featureName: item.cmdInfo?.featureInfo.name,
                        pluginName: item.cmdInfo?.pluginInfo.pluginInfo.name,
                        featureDesc: item.cmdInfo?.featureInfo.desc,
                        extInfo: { cmdDetailInfo: item }
                    }
                )
            }
            // 如果为异步搜索则使用 [...state.searchResult, ...resultData]
            const searchResult = resultData
            let hash = {}
            const newArr = searchResult.reduceRight((item, next) => {
                hash[next.key] ? '' : hash[next.key] = true && item.push(next);
                return item
            }, []);

            // 保存数据并初始化列表的选择游标
            return { ...state, searchResult: newArr, cursor: 0, relativeCursor: 1 };
        },

        // 重置搜索列表结果
        doResetSeachResult() {
            return { ...state, searchResult: [], cursor: 0, relativeCursor: 1, preSearch: null };
        },

        // 执行listPlugin
        doTriggerForListPlugin(state, { payload }) {
            try {
                const code = payload.payload.plugin.cmdInfo.featureInfo.code
                // 初始化
                eval(payload.renderJs)
                // 上下文
                const action = {
                    extInfo: payload.payload.extInfo,
                    input: payload.payload.input,
                    subInput: payload.payload.subInput,
                    type: payload.payload.type,
                    source: "search"
                }

                // 搜索显示的回调函数
                let theData = []
                const callbackSetList = (data) => {
                    if (Array.isArray(data)) {
                        theData = data
                    }
                }

                // 执行脚本中enter
                if (window.exports[code]) {
                    window.exports[code].enter(action, callbackSetList)
                    const placeholder = window.exports[code].placeholder
                    service.onEmit(asyncTopicConstants.doSetListPluginPlaceholder, placeholder)
                }

                return {
                    ...state,
                    searchResult: theData,
                    cursor: 0,
                    relativeCursor: 1,
                    searchDataSource: "codeDefine",
                    listPluginInfo: payload.payload
                };
            } catch (e) {
                console.info(e)
            }
        }
    },
    subscriptions: {

        // 监听搜索结果消息
        onSearchPlugin({ dispatch }) {
            return service.onListen(asyncTopicConstants.onSearchPlugin,
                (response) => {
                    if (response.success == true) {
                        // 组装数据
                        dispatch({
                            type: 'doMergeSeachResult', payload: {
                                searchResult: response.body.cmdInfos,
                            }
                        })
                        // 根据组装后的数据设置窗口高度
                        dispatch({ type: 'updateMainWinHeight' })
                    }
                }
            )
        },

        onSearchListReset({ dispatch }) {
            return service.onListen(asyncTopicConstants.resetSearchPlugin,
                (response) => {
                    if (response.success == true) {
                        dispatch({ type: 'doShowMain' })
                        // 组装数据
                        dispatch({ type: 'doResetSeachResult' })
                        // 根据组装后的数据设置窗口高度
                        dispatch({ type: 'updateMainWinHeight' })
                    }
                }
            )
        },

        /*
        * 监听执行list插件命令
        */
        onTriggerForListPlugin({ dispatch }) {
            return service.onListen(asyncTopicConstants.onTriggerForListPlugin,
                (response) => {
                    if (response.success == true) {
                        try {
                            dispatch({ type: "doTriggerForListPlugin", payload: response.body })
                        } catch (e) {
                            // todo 执行异常发送系统消息
                        }
                        dispatch({ type: 'updateMainWinHeight' })
                    }
                }
            )
        },

        /*
        * desc: 清空搜索列表
        */
        onEmptySearchResult({ dispatch }) {
            return service.onListen(asyncTopicConstants.doEmptySearchResult,
                (response) => {
                    dispatch({ type: 'doEmptySearchResult' })
                }
            )
        },

        /*
        * desc: 相应来自主窗口监听的键盘上下按键事件，选择插件
        */
        onKeyUpOrDown({ dispatch }) {
            return service.onListen(asyncTopicConstants.onKeyUpOrDown, (response) => {
                dispatch({ type: 'doKeyUpOrDown', payload: response.payload })
            })
        },

        /*
        * desc: 相应来自主窗口监听的键盘Enter键，执行插件
        */
        onKeyUpEnter({ dispatch }) {
            return service.onListen(asyncTopicConstants.onKeyEnter, (response) => {
                dispatch({ type: 'doKeyEnter' })
            })
        },

        /*
        * desc: 监听来自主渲染进程的搜索相关信息，用于保存搜索参数，及执行list插件的搜索
        */
        onSearchActionInfo({ dispatch }) {
            return service.onListen(asyncTopicConstants.doSearchPlugin, (response) => {
                // 对于list插件搜索不需要保存搜索上下文
                const type = response.payload.type
                if (type == "listPlugin") {
                    dispatch({ type: 'doSearchForListPlugin', payload: response.payload })
                    dispatch({ type: 'updateMainWinHeight' })
                } else {
                    dispatch({ type: 'save', payload: { searchActionInfo: response.payload } })
                }
            })
        },

    }


};


export default GlobalModel;
